package swing;

import control.MouseControl;
import redistool.RedisTool;
import utils.NodeUtils;
import utils.RedisHashkeyUtils;
import utils.RedisUtils;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.List;
import java.util.*;

/**
 * @version V1.0
 * @Title: 重写JTree
 * @Package
 * @Description:
 * @author: GaleBlade
 * @date:
 */
public class CommonTree extends JTree {

    private RedisTool redisTool;
    //使用list类型来记录db节点
    private List<DefaultMutableTreeNode> dbList = new ArrayList<>();
    //使用int类型来记录该树是视图中的第几棵树
    public int i;
    //使用Boolean类型来记录该树是否展开
    public Boolean isExpan = false;
    //redis连接信息，名称、地址、端口、密码
    public String name;
    private String host;
    private String port;
    private String auth;
    //使用list来记录db节点的高度
    private List<Integer> nodeCountList = new ArrayList<>();
    //记录位置和大小信息
    public int x = 5;
    public int y = 5;
    public int width = 24;
    public int height = 25;

    /**
     * 空的构造方法
     */
    public CommonTree(){}

    /**
     * 正式构造方法
     */
    public CommonTree(int i, DefaultMutableTreeNode top, String name, String host, String port, String auth, RedisTool redisTool){
        //调用父类构造方法
        super(top);
        //初始化参数
        initParams(i, name, host, port, auth, redisTool);
        //初始化根节点
        initTop(top);
        //初始化tree属性
        initProperty();
        //初始化nodeCountList
        initNodeCountList();
    }

    /**
     * 初始化参数
     */
    private void initParams(int i, String name, String host, String port, String auth, RedisTool redisTool){
        for (int j=0;j<16;j++){
            this.dbList.add(new DefaultMutableTreeNode(new NodeUtils(j,"db"+j)));
        }
        this.redisTool = redisTool;
        this.i = i;
        this.name = name;
        this.host = host;
        this.port = port;
        this.auth = auth;
        this.y = 5 + 25 * i;
    }

    /**
     * 初始化属性
     */
    private void initProperty(){
        //添加鼠标适配器
        MouseControl mouse = new MouseControl(redisTool, this);
        this.addMouseListener(mouse);
        //使用重写的TreeCellRenderer来自定义jtree的属性
        this.setCellRenderer(new TreeNodeRenderer());
        this.setFont(new Font("Menu.font", Font.PLAIN, 15));
        this.setBackground(Color.GRAY);
        this.setForeground(Color.WHITE);
        this.setBounds(x, y,12 * width, height);
        //设置jtree的行高
        this.setRowHeight(20);
        //添加选择事件
        this.addTreeSelectionListener(e -> {
            //获取当前选择的节点
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) this.getLastSelectedPathComponent();
            if (node == null)
                return;
            //获取节点中的类
            Object object = node.getUserObject();
            //如果选中的是db节点（树的第二层）
            if (node.getLevel() == 1){
                //把类转换为NodeUtils类
                NodeUtils nodeUtils = (NodeUtils) object;
                //获取节点编号为数据库编号
                redisTool.db = nodeUtils.no;
                redisTool.getRedisConnect(host, port, auth);
                //加载该db下的key作为叶子节点
                this.setNode(redisTool.db);
                redisTool.redisUtils.close();
            }
            //如果选中的是叶子节点
            if (node.isLeaf()) {
                //把类转换为RedisHashkeyUtils类
                RedisHashkeyUtils redisHashkeyUtils = (RedisHashkeyUtils) object;
                //获取key名
                redisTool.key = redisHashkeyUtils.hkey;
                //组装选中提示
                redisTool.topLabel.setText("已选 : " + this.name + " → db" + redisTool.db + " → " + redisTool.key);
            }
        });
    }

    /**
     * 初始化nodeCountList
     */
    private void initNodeCountList(){
        //初始化list为1，1为未展开
        for (int j=0;j<16;j++){
            nodeCountList.add(1);
        }
    }

    /**
     * 初始化根节点（top节点）
     */
    public void initTop(DefaultMutableTreeNode top){
        for (int i=0;i<16;i++){
            //删除所有子节点
            dbList.get(i).removeAllChildren();
            top.add(dbList.get(i));
        }
    }

    /**
     * 添加节点
     */
    public void addNode(int i,RedisHashkeyUtils hkey){
        dbList.get(i).add(new DefaultMutableTreeNode(hkey));
    }

    /**
     * 展开和收起redis节点时适配树的高度
     */
    public void change(){
        //获取根节点
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) this.getLastSelectedPathComponent();
        int heightOld = height;
        int heightNew;
        if (isExpan){
            heightNew = 25;
            height = 25;
            //删除所有子节点
            root.removeAllChildren();
            this.initTop(root);
        }else {
            heightNew = 340;
            height = 340;
            this.initNode();
        }
        //刷新树
        this.updateUI();
        this.setBounds(x, y,12 * width, height);
        //刷新treePanel
        redisTool.refreshPanel(this.i, this.name, 12 * width, heightOld, heightNew);
        //状态切换
        isExpan = !isExpan;
    }

    /**
     * 展开db节点方法
     */
    public void changeSize(){
        //返回最后选中的结点
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) this.getLastSelectedPathComponent();
        //如果不是叶子节点则展开
        if (!node.isLeaf()){
            //获得这个结点的名称
            String name = node.toString();
            String[] cache = name.split("[(]");
            //根据名称获取具体的数据库和key总数
            int db = Integer.parseInt(cache[0].replace("db", ""));
            int count = Integer.parseInt(cache[1].replace(")", ""));
            if (nodeCountList.get(db) == 1){
                //如果该节点为未展开状态则更新高度为展开后的高度，更新宽度为最大宽度
                nodeCountList.set(db, count);
                //获取节点中的类
                Object object = node.getUserObject();
                NodeUtils nodeUtils = (NodeUtils) object;
                //记录最大的width
                if (width < nodeUtils.width){
                    width = nodeUtils.width;
                }
            }else {
                //如果节点为展开状态则更新高度为1，宽度为25
                nodeCountList.set(db, 1);
                width = 24;
            }
            //计算这棵树的总高度
            int countAll = 0;
            for (int i : nodeCountList){
                countAll += i;
            }
            //根据总高度设置树所占的高度
            int heightOld = height;
            int heightNew = 21 * (countAll + 1);
            height = 21 * (countAll + 1);
            this.setBounds(x, y, 12 * width, height);
            //刷新treePanel
            redisTool.refreshPanel(this.i, this.name, 12 * width, heightOld, heightNew);
        }
    }

    /**
     * 给每个db节点下都添加一个“ - ”的叶子节点，方便展开
     */
    public void initNode(){
        //获取redis连接
        RedisUtils redisUtils = new RedisUtils(host,port,auth);
        for (int i=0;i<16;i++){
            //选择数据库
            redisUtils.select(i);
            //获取节点中的类
            Object object = this.dbList.get(i).getUserObject();
            NodeUtils nodeUtils = (NodeUtils) object;
            //赋值
            nodeUtils.count = redisUtils.jedis.dbSize().intValue();
            this.addNode(i,new RedisHashkeyUtils(" - "));
        }
        //操作完后关闭连接
        redisUtils.close();
    }

    /**
     * 加载db中的key并添加到树上作为叶子节点
     */
    public void setNode(int db){
        //选择数据库
        redisTool.redisUtils.select(db);
        //批量获取db下面的key值
        Set<String> keys = redisTool.redisUtils.jedis.keys("*");
        //使用TreeSet类型进行自然排序
        Set<String> sortKeys = new TreeSet<>(Comparator.naturalOrder());
        sortKeys.addAll(keys);
        if (keys.size() > 0){
            //获取tree的model
            DefaultTreeModel model = (DefaultTreeModel)this.getModel();
            //获取当前选择的节点
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) this.getLastSelectedPathComponent();
            //获取该节点下的第一个子节点
            DefaultMutableTreeNode FirstChild = (DefaultMutableTreeNode) selectedNode.getFirstChild();
            if (FirstChild != null && FirstChild.getParent() != null) {
                //删除指定节点
                model.removeNodeFromParent(FirstChild);
            }
            //获取节点中的类
            Object object = selectedNode.getUserObject();
            NodeUtils nodeUtils = (NodeUtils) object;
            int nodeWidth = 0;
            for (String key : sortKeys) {
                if (key.length() > nodeWidth){
                    nodeWidth = key.length();
                }
                this.addNode(db,new RedisHashkeyUtils(key));
            }
            nodeUtils.width = nodeWidth;
        }
    }

    /**
     * 刷新树的坐标和大小
     */
    public void refreshBounds(int height){
        this.y += height;
        this.setBounds(this.x, this.y, 12 * width, this.height);
        this.updateUI();
    }

    /**
     * 展开或折叠对应节点
     */
    public void expand(){
        //获取节点
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) this.getLastSelectedPathComponent();
        if (isExpan){
            this.expandPath(new TreePath(node));
        }else {
            this.collapsePath(new TreePath(node));
        }
    }

}
